/**
 *  Copyright (C) 2008-2013  Telosys project org. ( http://www.telosys.org/ )
 *
 *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *          http://www.gnu.org/licenses/lgpl.html
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.telosys.persistence.dao;

import java.sql.Connection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.telosys.persistence.Query;
import org.telosys.persistence.impl.EntityInfoImpl;
import org.telosys.persistence.mapping.EntityMapping;
import org.telosys.persistence.mapping.LinkMapping;
import org.telosys.persistence.sql.Criteria;
import org.telosys.persistence.sql.Criterion;
import org.telosys.persistence.sql.CriterionType;

/**
 * Standard entity DAO 
 * 
 * @author Laurent Guerin
 *
 * @param <T>
 */
public class EntityDAO<T> extends EntityAncestorDAO<T>
{
//	private EntityMapper<T> entityMapper = null ;
	
//	public EntityDAO ( EntityMapping<T> entityMapping ) //throws TelosysException
//	{
//		this( new EntityMapper<T>(entityMapping) );
//	}
//	
//	private EntityDAO( EntityMapper<T> entityMapper) 
//	{
//		super(entityMapper.getEntityClass(), entityMapper.getSqlRequests() );
//
//		this.entityMapper = entityMapper;
//	}

	public EntityDAO ( EntityMapping<T> entityMapping ) {
		super(entityMapping);
	}
	
//	@Override
//	protected int beanToTable(QueryContext queryContext, T entity) //throws TelosysException 
//	{
//		EntityMapper<T> entityMapper = getEntityMapper() ;
//		entityMapper.beanToTable(entity, queryContext);
//		return 0;
//	}
//	
//    //============================================================================
//    // Special mapping for tables with auto-incremented Primary Key ( for INSERT )
//    //============================================================================
//    @Override
//    protected int beanToTableWithoutAutoInc (QueryContext queryContext, T entity ) //throws TelosysException
//    {
//		EntityMapper<T> entityMapper = getEntityMapper() ;
//    	entityMapper.beanToTableWithoutAutoInc(entity, queryContext);
//		return 0;
//    }

//    //============================================================================
//    // Set auto-incremented attribute after INSERT operation 
//    //============================================================================
//    @Override
//	protected void setAutoIncrementedValue(T entity, long key) //throws TelosysException 
//	{
//		EntityMapper<T> entityMapper = getEntityMapper() ;
//    	// in specific DAO : entity.setId( (int) key );
//    	entityMapper.setAutoIncrementedValue(entity, key);
//	}

//	@Override
//	protected T createEntityWithPK(Object... primaryKeyValues) //throws TelosysException 
//	{		
//		EntityMapper<T> entityMapper = getEntityMapper() ;
//		return entityMapper.createEntityWithPK(primaryKeyValues);
//	}

//	@Override
//	protected void setPrimaryKey(QueryContext queryContext, T entity) //throws TelosysException 
//	{
//		EntityMapper<T> entityMapper = getEntityMapper() ;
//		entityMapper.setPrimaryKey(entity, queryContext);
//	}

//	@Override
//	protected int tableToBean(QueryContext queryContext, T entity) //throws TelosysException 
//	{
//		EntityMapper<T> entityMapper = getEntityMapper() ;
//		entityMapper.tableToBean(entity, queryContext);
//		return 0;
//	}    

	//============================================================================
    //  EXISTS
    //============================================================================
    /**
     * Tests if the Primary Key of the given Value Object exists in the database, <br>
     * using the default database
     * @param vo : the Value Object containing the Primary Key
     * @return : true if the primary key exists (else false)
     * @throws TelosysException
     */
    public boolean exists( T vo) //throws TelosysException
    {
        return super.doExists(vo);
    }
    
    /**
     * Tests if the Primary Key of the given Value Object exists in the database, <br>
     * using a specific database id  
     * @param vo : the Value Object containing the Primary Key
     * @param dbId : the database id to use
     * @return : true if the primary key exists (else false)
     * @throws TelosysException
     */
    public boolean exists( T vo, int dbId ) //throws TelosysException
    {
        return super.doExists(vo, dbId);
    }
    
    /**
     * Tests if the Primary Key of the given Value Object exists in the database, <br>
     * using a specific database connection  
     * @param vo : the Value Object containing the Primary Key
     * @param con : the connection to use
     * @return : true if the primary key exists (else false)
     * @throws TelosysException
     */
    public boolean exists( T vo, Connection con) // throws TelosysException
    {
        return super.doExists(vo, con);
    }
    
//    /**
//     * Tests if the Primary Key of the given Value Object exists in the database, <br>
//     * using a specific database session  
//     * @param vo : the Value Object containing the Primary Key
//     * @param dbSession : the database session to use
//     * @return : true if the primary key exists (else false)
//     * @throws TelosysException
//     */
//    public boolean exists( T vo, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doExists(vo, dbSession);
//    }

    //============================================================================
    //  LOAD
    //============================================================================
    /**
     * Loads an single Value Object from the database ( with SQL select )<br>
     * using the default database
     * @param  vo  : the Value Object to load
     * @return The number of bean loaded ( 1 or 0 if not found )
     * @throws TelosysException
     */
    public boolean load( T vo) //throws TelosysException
    {
        return super.doLoad(vo);
    }

    /**
     * Loads an single Value Object from the database ( with SQL select )<br>
     * with an optional SQL Select Clause ( ie "FOR UPDATE" ) <br>
     * using the default database
     * @param  vo  : the Value Object to load
     * @param  optionalClause : the optional clause ( ie "FOR UPDATE" )
     * @return The number of bean loaded ( 1 or 0 if not found )
     * @throws TelosysException
     */
    public boolean load( T vo, String optionalClause) // throws TelosysException
    {
        return super.doLoad(vo, optionalClause);
    }

    //------------------------------------------------------------------------------
    
    /**
     * Loads a single Value Object from the database ( with SQL select ) <br>
     * using a specific database id  
     * @param  vo  : the Value Object to load
     * @param  dbId : the database id to use
     * @return The number of bean loaded ( 1 or 0 if not found )
     * @throws TelosysException
     */
    public boolean load( T vo, int dbId ) // throws TelosysException
    {
        return super.doLoad(vo, dbId);
    }
  
    /**
     * Loads a single Value Object from the database ( with SQL select ) <br>
     * with an optional SQL Select Clause ( ie "FOR UPDATE" ) <br>
     * using a specific database id  
     * @param  vo  : the Value Object to load
     * @param  optionalClause : the optional clause ( ie "FOR UPDATE" )
     * @param  dbId : the database id to use
     * @return The number of bean loaded ( 1 or 0 if not found )
     * @throws TelosysException
     */
    public boolean load( T vo, String optionalClause, int dbId ) // throws TelosysException
    {
        return super.doLoad(vo, optionalClause, dbId);
    }
  
    //------------------------------------------------------------------------------
    
    /**
     * Loads a single Value Object from the database ( with SQL select ) <br>
     * using a specific database connection  
     * @param  vo  : the Value Object to load
     * @param  con : the connection to use
     * @return The number of bean loaded ( 1 or 0 if not found )
     * @throws TelosysException
     */
    public boolean load( T vo, Connection con) // throws TelosysException
    {
        return super.doLoad(vo, con);
    }

    /**
     * Loads a single Value Object from the database ( with SQL select ) <br>
     * with an optional SQL Select Clause ( ie "FOR UPDATE" ) <br>
     * using a specific database connection  
     * @param  vo  : the Value Object to load
     * @param  optionalClause : the optional clause ( ie "FOR UPDATE" )
     * @param  con : the connection to use
     * @return The number of bean loaded ( 1 or 0 if not found )
     * @throws TelosysException
     */
    public boolean load( T vo, String optionalClause, Connection con) // throws TelosysException
    {
        return super.doLoad(vo, optionalClause, con);
    }
  
    //------------------------------------------------------------------------------
    public T loadByKey(Connection con,  Object ... primaryKeyValues ) 
    {
    	return super.doLoadByPK(con, primaryKeyValues);
    }

    //------------------------------------------------------------------------------
    public T loadByKeyForUpdate(Connection con, String forUpdateString, Object ... primaryKeyValues ) 
    {
    	return super.doLoadByPKForUpdate(con, forUpdateString, primaryKeyValues);
    }
    
    
//    /**
//     * Loads a single Value Object from the database ( with SQL select ) <br>
//     * using a specific database session  
//     * @param  vo  : the Value Object to load
//     * @param  dbSession : the database session to use
//     * @return The number of bean loaded ( 1 or 0 if not found )
//     * @throws TelosysException
//     */
//    public boolean load( T vo, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doLoad(vo, dbSession);
//    }
  
//    /**
//     * Loads a single Value Object from the database ( with SQL select ) <br>
//     * with an optional SQL Select Clause ( ie "FOR UPDATE" ) <br>
//     * using a specific database session  
//     * @param  vo  : the Value Object to load
//     * @param  optionalClause : the optional clause ( ie "FOR UPDATE" )
//     * @param  dbSession : the database session to use
//     * @return The number of bean loaded ( 1 or 0 if not found )
//     * @throws TelosysException
//     */
//    public boolean load( T vo, String optionalClause, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doLoad(vo, optionalClause, dbSession);
//    }
  
    //============================================================================
    //  SAVE
    //============================================================================
    /**
     * Saves a single Value Object in the database ( with SQL insert or update )<br>
     * using the default database
     * @param  vo : the Value Object to save
     * @return the JDBC return value ( number of rows that were affected ) : allways 1
     * @throws TelosysException
     */
    public int save( T vo) // throws TelosysException
    {
        return super.doSave(vo);
    }
  
    /**
     * Saves a single Value Object in the database ( with SQL insert or update ) <br>
     * using a specific database id
     * @param  vo : the Value Object to save
     * @param  dbId : the database Id to use
     * @return the JDBC return value ( number of rows that were affected ) : allways 1
     * @throws TelosysException
     */
    public int save( T vo, int dbId) // throws TelosysException
    {
        return super.doSave(vo, dbId);
    }
  
    /**
     * Saves a single Value Object in the database ( with SQL insert or update ) <br>
     * using a specific database connection
     * @param  vo : the Value Object to save
     * @param  con : the connection to use
     * @return the JDBC return value ( number of rows that were affected ) : allways 1
     * @throws TelosysException
     */
    public int save( T vo, Connection con) // throws TelosysException
    {
        return super.doSave(vo, con);
    }
  
//    /**
//     * Saves a single Value Object in the database ( with SQL insert or update ) <br>
//     * using a specific database session
//     * @param  vo : the Value Object to save
//     * @param  dbSession : the database session to use
//     * @return the JDBC return value ( number of rows that were affected ) : allways 1
//     * @throws TelosysException
//     */
//    public int save( T vo, DatabaseSession session) throws TelosysException
//    {
//        return super.doSave(vo, session);
//    }
  
    //============================================================================
    //  INSERT
    //============================================================================
//    private void setAutoIncrementedKey( T vo, Long key) 
//    {
//        vo.setId( key.intValue() );
//    }
	
    /**
     * Inserts a single Value Object in the database ( with SQL insert )<br>
     * using the default database
     * @param  vo : the Value Object to insert
     * @return the JDBC return value ( number of rows that were affected )
     * @throws TelosysException
     */
    public int insert( T vo) // throws TelosysException
    {
//        Long key = super.doInsertKeyGen(vo);
//        setAutoIncrementedKey(vo, key);
//        return 1 ;		
        return super.doInsert(vo);    	
    }
  
    /**
     * Inserts a single Value Object in the database ( with SQL insert ) <br>
     * using a specific database id
     * @param  vo : the Value Object to insert
     * @param  dbId : the database id to use
     * @return the JDBC return value ( number of rows that were affected )
     * @throws TelosysException
     */
    public int insert( T vo, int dbId ) // throws TelosysException
    {
//        Long key = super.doInsertKeyGen(vo, dbId);
//        setAutoIncrementedKey(vo, key);
//        return 1 ;
        return super.doInsert(vo, dbId);    	
    }
    
    /**
     * Inserts a single Value Object in the database ( with SQL insert ) <br>
     * using a specific database connection
     * @param  vo : the Value Object to insert
     * @param  con : the connection to use
     * @return the JDBC return value ( number of rows that were affected )
     * @throws TelosysException
     */
    public int insert( T vo, Connection con) // throws TelosysException
    {
//        Long key = super.doInsertKeyGen(vo, con);
//        setAutoIncrementedKey(vo, key);
//        return 1 ;
        return super.doInsert(vo, con);    	
    }
     
//    /**
//     * Inserts a single Value Object in the database ( with SQL insert ) <br>
//     * using a specific database session
//     * @param  vo : the Value Object to insert
//     * @param  dbSession : the database session to use
//     * @return the JDBC return value ( number of rows that were affected )
//     * @throws TelosysException
//     */
//    public int insert( T vo, DatabaseSession dbSession) throws TelosysException
//    {
////        Long key = super.doInsertKeyGen(vo, dbSession);
////        setAutoIncrementedKey(vo, key);
////        return 1 ;
//        return super.doInsert(vo, dbSession);    	
//    }

    //============================================================================
    //  INSERT WITH KEY GENERATION
    //============================================================================
    /**
     * Inserts a single Value Object in the database ( with SQL insert ) <br>
     * using the default database
     * and returns the value of the auto-generated key 
     * @param  vo : the Value Object to insert
     * @return the generated key ( wrapped in a Long object ) or null if none
     * @throws TelosysException
     */
    public long insertKeyGen( T vo) // throws TelosysException
    {
        return super.doInsertKeyGen(vo);
    }
  
    /**
     * Inserts a single Value Object in the database ( with SQL insert ) <br>
     * using a specific database id
     * and returns the value of the auto-generated key 
     * @param  vo : the Value Object to insert
     * @param  dbId : the database id to use
     * @return the generated key ( wrapped in a Long object ) or null if none
     * @throws TelosysException
     */
    public long insertKeyGen( T vo, int dbId ) // throws TelosysException
    {
        return super.doInsertKeyGen(vo, dbId);
    }
    
    /**
     * Inserts a single Value Object in the database ( with SQL insert ) <br>
     * using a specific database connection
     * and returns the value of the auto-generated key 
     * @param  vo : the Value Object to insert
     * @param  con : the connection to use
     * @return the generated key ( wrapped in a Long object ) or null if none
     * @throws TelosysException
     */
    public long insertKeyGen( T vo, Connection con) // throws TelosysException
    {
        return super.doInsertKeyGen(vo, con);
    }
     
//    /**
//     * Inserts a single Value Object in the database ( with SQL insert ) <br>
//     * using a specific database session
//     * and returns the value of the auto-generated key 
//     * @param  vo : the Value Object to insert
//     * @param  dbSession : the database session to use
//     * @return the generated key ( wrapped in a Long object ) or null if none
//     * @throws TelosysException
//     */
//    public long insertKeyGen( T vo, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doInsertKeyGen(vo, dbSession);
//    }
    
    //============================================================================
    //  UPDATE
    //============================================================================
    /**
     * Updates a single Value Object in the database ( with SQL update )<br>
     * using the default database
     * @param  vo : the Value Object to update
     * @return the JDBC return value ( number of rows that were affected )
     * @throws TelosysException
     */
    public int update( T vo) // throws TelosysException
    {
        return super.doUpdate(vo); 
    }
    
    /**
     * Updates a single Value Object in the database ( with SQL update )<br>
     * using a specific database id
     * @param  vo : the Value Object to update
     * @param  dbId : the database id to use
     * @return the JDBC return value ( number of rows that were affected )
     * @throws TelosysException
     */
    public int update( T vo, int dbId) // throws TelosysException
    {
        return super.doUpdate(vo, dbId); 
    }
    
    /**
     * Updates a single Value Object in the database ( with SQL update ) <br>
     * using a specific database connection
     * @param  vo : the Value Object to update
     * @param  con : the database connection to use
     * @return the JDBC return value ( number of rows that were affected )
     * @throws TelosysException
     */
    public int update( T vo, Connection con) // throws TelosysException
    {
        return super.doUpdate(vo, con);
    }
    
//    /**
//     * Updates a single Value Object in the database ( with SQL update ) <br>
//     * using a specific database session
//     * @param  vo : the Value Object to update
//     * @param  dbSession : the database session to use
//     * @return the JDBC return value ( number of rows that were affected )
//     * @throws TelosysException
//     */
//    public int update( T vo, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doUpdate(vo, dbSession);
//    }

    //============================================================================
    //  DELETE
    //============================================================================
    /**
     * Deletes a single Value Object in the database ( with SQL delete ) <br>
     * using the default database
     * @param  vo : the Value Object to delete
     * @return the JDBC return value ( number of rows that were affected )
     * @throws TelosysException
     */
    public int delete( T vo) // throws TelosysException
    {
        return super.doDelete(vo);
    }
  
    /**
     * Deletes a single Value Object in the database ( with SQL delete ) <br>
     * using a specific database id
     * @param  vo : the Value Object to delete
     * @param  dbId : the database id to use
     * @return the JDBC return value ( number of rows that were affected )
     * @throws TelosysException
     */
    public int delete(T vo, int dbId) // throws TelosysException
    {
        return super.doDelete(vo, dbId); 
    }
  
    /**
     * Deletes a single Value Object in the database ( with SQL delete ) <br>
     * using a specific database connection
     * @param  vo : the Value Object to delete
     * @param  con : the database connection to use
     * @return the JDBC return value ( number of rows that were affected )
     * @throws TelosysException
     */
    public int delete(T vo, Connection con) // throws TelosysException
    {
        return super.doDelete(vo, con); 
    }
  
//    /**
//     * Deletes a single Value Object in the database ( with SQL delete ) <br>
//     * using a specific database session
//     * @param  vo : the Value Object to delete
//     * @param  dbSession : the database session to use
//     * @return the JDBC return value ( number of rows that were affected )
//     * @throws TelosysException
//     */
//    public int delete(T vo, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doDelete(vo, dbSession); 
//    }

    //============================================================================
    //   LOAD LIST ( SELECT )
    //============================================================================
    /**
     * Loads a list of Value Objects according with the given query <br>
     * using the default database
     * @param query
     * @param list
     * @return
     * @throws TelosysException
     */
    public int loadList(List<T> list, Query<T> query ) // throws TelosysException
    {
        return super.doLoad(list, query); 
    }

    /**
     * Loads a list of Value Objects according with the given query <br>
     * using a specific database id
     * @param query
     * @param list
     * @param dbId
     * @return
     * @throws TelosysException
     */
    public int loadList(List<T> list, Query<T> query, int dbId) // throws TelosysException
    {
        return super.doLoad(list, query, dbId);
    }
    
    /**
     * Loads a list of Value Objects according with the given query <br>
     * using a specific database connection
     * @param query
     * @param list
     * @param dbConnection
     * @return
     * @throws TelosysException
     */
    public int loadList(List<T> list, Query<T> query, Connection dbConnection) // throws TelosysException
    {
        return super.doLoad(list, query, dbConnection);
    }
    
//    /**
//     * Loads a list of Value Objects according with the given query <br>
//     * using a specific database session
//     * @param query
//     * @param list
//     * @param dbSession
//     * @return
//     * @throws TelosysException
//     */
//    public int load(List<T> list, Query<T> query, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doLoad(list, query, dbSession);
//    }

    
    //============================================================================
    //   DELETE LIST BY QUERY CRITERIA
    //============================================================================
    /**
     * Deletes a list of records according with the given query criteria, <br>
     * using the default database
     * @param query
     * @return
     * @throws TelosysException
     */
    public int deleteByQuery(Query<T> query) // throws TelosysException
    {
        return super.doDelete(query);
    }

    /**
     * Deletes a list of records according with the given query criteria, <br>
     * using a specific database id  
     * @param query
     * @param dbId
     * @return
     * @throws TelosysException
     */
    public int deleteByQuery(Query<T> query, int dbId) // throws TelosysException
    {
        return super.doDelete(query, dbId);
    }

    /**
     * Deletes a list of records according with the given query criteria, <br>
     * using a specific database connection  
     * @param query
     * @param dbConnection
     * @return
     * @throws TelosysException
     */
    public int deleteByQuery(Query<T> query, Connection dbConnection) // throws TelosysException
    {
        return super.doDelete(query, dbConnection);
    }
    
//    /**
//     * Deletes a list of records according with the given query criteria, <br>
//     * using a specific database session
//     * @param query
//     * @param dbSession
//     * @return
//     * @throws TelosysException
//     */
//    public int delete(Query<T> query, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doDelete(query, dbSession);
//    }

    //============================================================================
    //   INSERT VO-LIST ITEMS
    //============================================================================
//    /**
//     * Inserts each Value Object of the given list (item by item), <br>
//     * using the default database
//     * @param list
//     * @return
//     * @throws TelosysException
//     */
//    public int insertList(List<T> list) throws TelosysException
//    {
//        return super.doInsertListItems(list);
//    }
//    
//    /**
//     * Inserts each Value Object of the given list (item by item), <br>
//     * using a specific database id  
//     * @param list
//     * @param dbId
//     * @return
//     * @throws TelosysException
//     */
//    public int insertList(List<T>, int dbId) throws TelosysException
//    {
//        return super.doInsertListItems(list, dbId);
//    }
//    
//    /**
//     * Inserts each Value Object of the given list (item by item), <br>
//     * using a specific database connection  
//     * @param list
//     * @param dbConnection
//     * @return
//     * @throws TelosysException
//     */
//    public int insertList(List<T>, Connection dbConnection) throws TelosysException
//    {
//        return super.doInsertListItems(list, dbConnection);
//    }
//    
//    /**
//     * Inserts each Value Object of the given list (item by item), <br>
//     * using a specific database session
//     * @param list
//     * @param dbSession
//     * @return
//     * @throws TelosysException
//     */
//    public int insertList(List<T>, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doInsertListItems(list, dbSession);
//    }

    //============================================================================
    //   INSERT GENERIC LIST ITEMS
    //============================================================================
    /**
     * Inserts each Value Object of the given list (item by item), <br>
     * using the default database
     * @param list
     * @return
     * @throws TelosysException
     */
    public int insertList(List<T> list) // throws TelosysException
    {
        return super.doInsert(list);
    }
    
    /**
     * Inserts each Value Object of the given list (item by item), <br>
     * using a specific database id  
     * @param list
     * @param dbId
     * @return
     * @throws TelosysException
     */
    public int insertList(List<T> list, int dbId) // throws TelosysException
    {
        return super.doInsert(list, dbId);
    }
    
    /**
     * Inserts each Value Object of the given list (item by item), <br>
     * using a specific database connection  
     * @param list
     * @param dbConnection
     * @return
     * @throws TelosysException
     */
    public int insertList(List<T> list, Connection dbConnection) // throws TelosysException
    {
        return super.doInsert(list, dbConnection);
    }
    
//    /**
//     * Inserts each Value Object of the given list (item by item), <br>
//     * using a specific database session
//     * @param list
//     * @param dbSession
//     * @return
//     * @throws TelosysException
//     */
//    public int insert(List<T> list, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doInsert(list, dbSession);
//    }

    //============================================================================
    //   UPDATE VO-LIST ITEMS
    //============================================================================
//    /**
//     * Updates each Value Object of the given list (item by item), <br>
//     * using the default database
//     * @param list
//     * @return
//     * @throws TelosysException
//     */
//    public int updateList(TList list) throws TelosysException
//    {
//        return super.doUpdateListItems(list);
//    }
//    
//    /**
//     * Updates each Value Object of the given list (item by item), <br>
//     * using a specific database id  
//     * @param list
//     * @param dbId
//     * @return
//     * @throws TelosysException
//     */
//    public int updateList(TList list, int dbId) throws TelosysException
//    {
//        return super.doUpdateListItems(list, dbId);
//    }
//    
//    /**
//     * Updates each Value Object of the given list (item by item), <br>
//     * using a specific database connection  
//     * @param list
//     * @param dbConnection
//     * @return
//     * @throws TelosysException
//     */
//    public int updateList(TList list, Connection dbConnection) throws TelosysException
//    {
//        return super.doUpdateListItems(list, dbConnection);
//    }
//    
//    /**
//     * Updates each Value Object of the given list (item by item), <br>
//     * using a specific database session
//     * @param list
//     * @param dbSession
//     * @return
//     * @throws TelosysException
//     */
//    public int updateList(TList list, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doUpdateListItems(list, dbSession);
//    }
    
    //============================================================================
    //   UPDATE GENERIC LIST ITEMS
    //============================================================================
    /**
     * Updates each Value Object of the given list (item by item), <br>
     * using the default database
     * @param list
     * @return
     * @throws TelosysException
     */
    public int updateList(List<T> list) // throws TelosysException
    {
        return super.doUpdate(list);
    }
    
    /**
     * Updates each Value Object of the given list (item by item), <br>
     * using a specific database id  
     * @param list
     * @param dbId
     * @return
     * @throws TelosysException
     */
    public int updateList(List<T> list, int dbId) // throws TelosysException
    {
        return super.doUpdate(list, dbId);
    }
    
    /**
     * Updates each Value Object of the given list (item by item), <br>
     * using a specific database connection  
     * @param list
     * @param dbConnection
     * @return
     * @throws TelosysException
     */
    public int updateList(List<T> list, Connection dbConnection) // throws TelosysException
    {
        return super.doUpdate(list, dbConnection);
    }
    
//    /**
//     * Updates each Value Object of the given list (item by item), <br>
//     * using a specific database session
//     * @param list
//     * @param dbSession
//     * @return
//     * @throws TelosysException
//     */
//    public int update(List<T> list, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doUpdate(list, dbSession);
//    }

    //============================================================================
    //   DELETE VO-LIST ITEMS
    //============================================================================
//    /**
//     * Deletes each Value Object of the given list (item by item), <br>
//     * using the default database
//     * @param list
//     * @return
//     * @throws TelosysException
//     */
//    public int deleteList(TList list) throws TelosysException
//    {
//        return super.doDeleteListItems(list);
//    }
//    
//    /**
//     * Deletes each Value Object of the given list (item by item), <br>
//     * using a specific database id  
//     * @param list
//     * @param dbId
//     * @return
//     * @throws TelosysException
//     */
//    public int deleteList(TList list, int dbId) throws TelosysException
//    {
//        return super.doDeleteListItems(list, dbId);
//    }
//    
//    /**
//     * Deletes each Value Object of the given list (item by item), <br>
//     * using a specific database connection  
//     * @param list
//     * @param dbConnection
//     * @return
//     * @throws TelosysException
//     */
//    public int deleteList(TList list, Connection dbConnection) throws TelosysException
//    {
//        return super.doDeleteListItems(list, dbConnection);
//    }
//    
//    /**
//     * Deletes each Value Object of the given list (item by item), <br>
//     * using a specific database session
//     * @param list
//     * @param dbSession
//     * @return
//     * @throws TelosysException
//     */
//    public int deleteList(TList list, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doDeleteListItems(list, dbSession);
//    }

    //============================================================================
    //   DELETE GENERIC LIST ITEMS
    //============================================================================
    /**
     * Deletes each Value Object of the given list (item by item), <br>
     * using the default database
     * @param list
     * @return
     * @throws TelosysException
     */
    public int deleteList(List<T> list) // throws TelosysException
    {
        return super.doDelete(list);
    }
    
    /**
     * Deletes each Value Object of the given list (item by item), <br>
     * using a specific database id  
     * @param list
     * @param dbId
     * @return
     * @throws TelosysException
     */
    public int deleteList(List<T> list, int dbId) // throws TelosysException
    {
        return super.doDelete(list, dbId);
    }
    
    /**
     * Deletes each Value Object of the given list (item by item), <br>
     * using a specific database connection  
     * @param list
     * @param dbConnection
     * @return
     * @throws TelosysException
     */
    public int deleteList(List<T> list, Connection dbConnection) // throws TelosysException
    {
        return super.doDelete(list, dbConnection);
    }
    
//    /**
//     * Deletes each Value Object of the given list (item by item), <br>
//     * using a specific database session
//     * @param list
//     * @param dbSession
//     * @return
//     * @throws TelosysException
//     */
//    public int delete(List<T> list, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doDelete(list, dbSession);
//    }

    //============================================================================
    //   COUNT
    //============================================================================
    /**
     * Counts the number of records according with the given query, <br>
     * using the default database
     * @param query
     * @return
     * @throws TelosysException
     */
    public int count(Query<T> query) // throws TelosysException
    {
        return super.doCount(query);
    }
    
    /**
     * Counts the number of records according with the given query, <br>
     * using a specific database id  
     * @param query
     * @param dbId
     * @return
     * @throws TelosysException
     */
    public int count(Query<T> query, int dbId) // throws TelosysException
    {
        return super.doCount(query, dbId);
    }
    
    /**
     * Counts the number of records according with the given query, <br>
     * using a specific database connection  
     * @param query
     * @param dbConnection
     * @return
     * @throws TelosysException
     */
    public int count(Query<T> query, Connection dbConnection) // throws TelosysException
    {
        return super.doCount(query, dbConnection);
    }
    
//    /**
//     * Counts the number of records according with the given query, <br>
//     * using a specific database session
//     * @param query
//     * @param dbSession
//     * @return
//     * @throws TelosysException
//     */
//    public int count(Query<T> query, DatabaseSession dbSession) throws TelosysException
//    {
//        return super.doCount(query, dbSession);
//    }

//	@Override
//	public String toString() 
//	{
//		EntityMapper<T> entityMapper = getEntityMapper() ;
//		StringBuffer sb = new StringBuffer();
//		sb.append("DAO for " );
//		sb.append( entityMapper != null ? entityMapper.getClass() : "(no entity mapper !)") ;
//		
//		return sb.toString();
//	}

	/**
	 * Returns entity information (mapping info)
	 * @return
	 */
	public EntityInfoImpl getEntityInfo() {
		EntityMapper<T> entityMapper = getEntityMapper() ;
		return entityMapper.toEntityInfo() ;
	}

    //-------------------------------------------------------------------------------------------------
    // LINKS "TO ONE"
    //-------------------------------------------------------------------------------------------------
    /**
     * Returns the key parts values for a link
     * @param entity
     * @param linkClass
     * @return
     */
    public Object[] getLinkToOneKeyParts(Object entity, Class<?> linkClass ) {
		EntityMapper<T> entityMapper = getEntityMapper() ;
    	return entityMapper.getLinkToOneKeyParts(entity, linkClass) ;
    }

    /**
     * Returns the key parts values for a link
     * @param entity
     * @param linkClass
     * @param linkName
     * @return
     */
    public Object[] getLinkToOneKeyParts(Object entity, Class<?> linkClass, String linkName ) {
		EntityMapper<T> entityMapper = getEntityMapper() ;
    	return entityMapper.getLinkToOneKeyParts(entity, linkClass, linkName) ;
    }

    //-------------------------------------------------------------------------------------------------
    // LINKS "TO MANY"
    //-------------------------------------------------------------------------------------------------
    /**
     * Returns the criteria (with param values set) for a link
     * @param entity
     * @param linkClass
     * @return
     */
    public Criteria getLinkToManyCriteria(Object entity, Class<?> linkClass ) {
		EntityMapper<T> entityMapper = getEntityMapper() ;
    	LinkMapping linkMapping = entityMapper.getLinkToManyMappingByType(linkClass) ;
    	return buildCriteria( entity, linkMapping );
    }
    /**
     * Returns the criteria (with param values set) for a link
     * @param entity
     * @param linkClass
     * @param linkName
     * @return
     */
    public Criteria getLinkToManyCriteria(Object entity, Class<?> linkClass, String linkName ) {
		EntityMapper<T> entityMapper = getEntityMapper() ;
    	LinkMapping linkMapping = entityMapper.getLinkToManyMappingByName(linkClass, linkName);
    	return buildCriteria( entity, linkMapping );
    }
    
    /**
     * Builds the criteria for a query referencing the entity as a Foreign Key 
     * @param entity
     * @param linkMapping
     * @return
     */
    private Criteria buildCriteria( Object entity, LinkMapping linkMapping ) {
    	
		EntityMapper<T> entityMapper = getEntityMapper() ;
		LinkedList<Criterion> listOfCriterion = new LinkedList<Criterion> ();
		Map<String,Object> parameters = new HashMap<String,Object>();
		
		String[] keyParts = linkMapping.getKeyParts();
		int keyPartIndex = 0 ;
		for ( String fieldName : keyParts ) {
			//--- Criterion definition ( ie "$publisherId = ?", TYPE, "publisherId" ) 
			// TODO : invalid entity : do not use current entity
//			FieldMapper    fieldMapper   = entityMapper.getFieldMapper(fieldName);
//			if ( null == fieldMapper ) {
//				throw new TelosysRuntimeException("No FieldMapper for field '" + fieldName + "' in " + entityMapper.getEntityClass() );
//			}
//			CriterionType  criterionType = CriterionType.typeForClass( fieldMapper.getFieldClass() ) ;
			
			FieldMapper    fieldMapper   =  entityMapper.getKeyFieldMapper(keyPartIndex) ;
			
			CriterionType  criterionType = CriterionType.typeForClass( fieldMapper.getFieldClass() ) ;

			Criterion criterion = new Criterion( "$"+fieldName+" = ?", criterionType, fieldName ) ;

			listOfCriterion.add(criterion);
			
			//--- Criterion value  
			//Object criterionValue = entityMapper.getFieldValue(entity, fieldName);
			Object criterionValue = fieldMapper.getValue(entity);
			parameters.put(fieldName, criterionValue);
			
			keyPartIndex++ ;
		}
		
		
		Criterion[] voidArray = {} ;
		Criterion[] arrayOfCriterion = listOfCriterion.toArray( voidArray );
		
		Criteria criteria = new Criteria(arrayOfCriterion);
		
		//--- Apply values ( here foreign key )
		criteria.applyParameters(parameters);
		
		return criteria ;
    }
    
}
